$(function() {
	app.init();
	
	app.displayArea('main');
});

var app = {
	_player : null,

	_areas : null,
	_types : {},
	_enemyTypes : {},
	
	_freeze : false,
	
	_currentArea : '',
	_lastLocation : null,
	_lastActiveLocations : [],
	_stage : null,
	_log : null,
	
	init : function() {
		var that = this;
		
		this._player = this.createPlayer();
		
		this._stage = $('<div>').attr('id', 'areaStage').appendTo('#body');
		this._log = $('#battleLog');
		
		$(document).keypress(function(event) {
			var directions = {
				37 : 'left',
				38 : 'up',
				39 : 'right',
				40 : 'down'
			};
			
			if (that._freeze) {
				return false;
			}
			
			that.move(directions[event.keyCode]);
			
			return false;
		});
		
		this.initAreas();
	},
	
	loadAreas : function(areas) {
		this._areas = areas;
	},
	
	loadTypes : function(types) {
		this._types = types;
	},
	
	loadEnemies : function(list) {
		this._enemyTypes = list;
	},
	
	initAreas : function() {
		var that = this;
		
		$.each(this._areas, function(id, area) {
			var areaLayer = $('<div>').addClass('area').attr('id', 'area-' + id);
			
			this._currentArea = id;
			
			for (var y = 0; y < area.map.length; y++) {
				for (var x = 0; x < area.map[y].length; x++) {
					var location = $('<div>').addClass('location').attr('id', 'area-' + id + '-location-' + x + '-' + y);
					location.addClass(area.map[y][x]);
					
					if (x == 0) {
						location.addClass('first');
					}
					
					if (x == area.map[y].length - 1) {
						location.addClass('last');
					}
					
					location.appendTo(areaLayer);
				}
			}
			
			for (var way in area.ways) {
				var selector = area.ways[way].coords.replace(/(\d+):(\d+)/, '#area-' + id + '-location-$1-$2');
				$(selector, areaLayer).addClass(way == 'start' ? 'start' : 'exit');
			}
			
			areaLayer.appendTo(that._stage);
		});
	},
	
	displayArea : function(id, location) {
		var area, coords;
		
		area = this._areas[id];
		location = area.ways[location] || area.ways.start;
		coords = location.coords.split(':');
		
		$('#area-' + this._currentArea).hide();
		this._currentArea = id;
		
		this.setCurrent(coords[0], coords[1]);
		
		$('#area-' + id).show();
	},
	
	setCurrent : function(posX, posY) {
		var sight = app.player.sight;
		var px = 0, py = 0, cell, type;
		
		if (this._lastLocation) {
			$(this._lastLocation).removeClass('current');
		}
		
		if (this._lastActiveLocations.length > 0) {
			$.each(this._lastActiveLocations, function(index, item) {
				$(item).removeClass('active');
			});
			
			this._lastActiveLocations = [];
		}
		
		this._lastLocation = $('#area-' + this._currentArea + '-location-' + posX + '-' + posY).addClass('current');
		
		for (var x = -sight; x < sight + 1; x++) {
			for (var y = -sight; y < sight + 1; y++) {
				if ((Math.abs(x) + Math.abs(y)) <= sight) {
					px = +posX + x;
					py = +posY + y;
					cell = $('#area-' + this._currentArea + '-location-' + px + '-' + py);
					
					if (cell.size()) {
						type = app._types[app._areas[app._currentArea].map[py][px]];
						
						if (!type.obstacle) {
							this._lastActiveLocations.push(cell.addClass('active'));
						}
					}
				}
			}
		}
	},
	
	move : function(direction) {
		var steps = {
			'left' : [-1, 0],
			'up' : [0, -1],
			'right' : [1, 0],
			'down' : [0, 1]
		};
		var location = this._lastLocation;
		var coords = location.attr('id').replace(/^.*location\-/, '').split('-');
		var step = steps[direction];
		var newCoords = [+coords[0] + step[0], +coords[1] + step[1]];
		var newLocationObject = $('#area-' + this._currentArea + '-location-' + newCoords[0] + '-' + newCoords[1]);
		var area = this._areas[this._currentArea];
		var newLocation = area && area.map && area.map[newCoords[1]] && this._types[area.map[newCoords[1]][newCoords[0]]];
		
		if (!newLocationObject.size() || !newLocation || newLocation.obstacle) {
			return false;
		}
		
		this.setCurrent(newCoords[0], newCoords[1]);
		
		for (var id in area.ways) {
			if ((newCoords[0] + ':' + newCoords[1]) == area.ways[id].coords && area.ways[id].area) {
				this.displayArea(area.ways[id].area, area.ways[id].location);
			}
		}
		
		this.checkFight(area, this._lastLocation);
	},
	
	checkFight : function(area, location) {
		var fightChance, enemyType;
		
		if (!area.enemies) {
			return false;
		}
		
		fightChance = Math.floor(Math.random() * 100);
		
		if (area.enemies) {
			for (var i in area.enemies) {
				if (fightChance > i) {
					continue;
				}

				enemyType = area.enemies[i];
				
				if (fightChance <= i) {
					break;
				}
			}
		}
		
		if (enemyType) {
			this.fight(enemyType);
		}
	},
	
	/**
	 * Start fight
	 */
	fight : function(type) {
		var enemy = this.createEnemy(type);
		var s1, s2, that = this;
		
		if (Math.random() <= .5) {
			s1 = this._player;
			s2 = enemy;
		}
		else {
			s1 = enemy;
			s2 = this._player;
		}
		
		this.clearLog();
		this.log(s1.name + ' attacks ' + s2.name + '!');
		
		do {
			var damage;
			
			if (s1.canHit()) {
				damage = s1.getDamage();
				s2.health -= damage;
				this.log(s1.name + ' hits ' + s2.name + ' for ' + damage + ' damage!');
				
				if (s2.isDead()) {
					this.log(s2.name + ' dies');
					break;
				}
			}
			else {
				this.log(s1.name + ' failed to hit ' + s2.name);
			}
			
			var tmp = s1;
			s1 = s2;
			s2 = tmp;
		} while (true);
		
		this.toggleStage();
		this._log.fadeIn('fast').delay(2000).fadeOut('slow', function() {
			that.toggleStage();
		});
		
		return true;
	},
	
	createEnemy : function(type) {
		if (typeof type != 'object') {
			type = this._enemyTypes[type];
		}
		
		return $.extend(true, {}, app.unit, app.mob, type);
	},
	
	createPlayer : function() {
		return $.extend(true, {}, app.unit, app.player);
	},
	
	clearLog : function() {
		this._log.empty();
	},
	
	log : function(msg) {
		$('<div>').html(msg).appendTo(this._log);
	},
	
	toggleStage : function() {
		this._freeze = this._freeze ? false : true;
	}
};

app.unit = {
	damage : 1,
	health : 50,
	hit : .5,
	
	canHit : function() {
		return Math.random() <= this.hit;
	},
	
	getDamage : function() {
		return this.damage;
	},
	
	isDead : function() {
		return this.health <= 0;
	}
};

app.player = {
	name : 'Player',
	sight : 1
};

app.mob = {};

(function() {
	var areas = {
		main : {
			ways : {
				start : {
					coords : '0:0'
				},
				left : {
					coords : '7:0',
					area : 'level1'
				},
				down : {
					coords : '7:4',
					area : 'level2'
				}
			},
			enemies : {
				10 : 'rat'
			},
			map : [
				['cell', 'cell', 'wall', 'cell', 'cell', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'wall', 'cell', 'wall', 'cell', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'cell', 'cell', 'cell', 'wall'],
				['cell', 'cell', 'wall', 'cell', 'cell', 'wall', 'cell', 'wall'],
				['wall', 'cell', 'wall', 'cell', 'wall', 'wall', 'cell', 'cell']
			]
		},
		level1 : {
			ways : {
				start : {
					coords : '3:3',
					area : 'main',
					location : 'left'
				},
				exit : {
					coords : '0:0',
					area : 'main'
				}
			},
			enemies : {
				30 : 'rat'
			},
			map : [
				['cell', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'wall']
			]
		},
		level2 : {
			ways : {
				start : {
					coords : '3:3',
					area : 'main',
					location : 'down'
				},
				exit : {
					coords : '0:0',
					area : 'main'
				}
			},
			map : [
				['cell', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'cell', 'wall', 'cell'],
				['wall', 'cell', 'wall', 'wall', 'wall', 'cell'],
				['wall', 'cell', 'cell', 'cell', 'cell', 'cell'],
				['wall', 'wall', 'wall', 'wall', 'wall', 'wall']
			]
		}
	};
	
	var types = {
		'cell' : {},
		'wall' : {
			obstacle : true,
			breakable : false
		}
	};
	
	var enemies = {
		'rat' : {
			name : 'Rat',
			health : 10,
			damage : 1
		}
	};
	
	app.loadAreas(areas);
	app.loadTypes(types);
	app.loadEnemies(enemies);
})();